#!/usr/bin/env python
# -*- coding:utf-8 -*-
from flask import current_app
from controller.administratorTokenController import AdministratorTokenController
from itsdangerous import Serializer, TimestampSigner
from models.administratorTokenModel import AdministratorToken
from app import db
from utils import commons
from utils.loggings import loggings
from utils.response_code import RET
from models.administrator import Administrator
from models.user import User


class AdministratorTokenService(AdministratorTokenController):

    # 生成token
    @classmethod
    def create_token(cls, user_id, user_type):

        """
        生成新的token
        :param user_type: 用户类型，0--学生用户；1--管理员；
        :param user_id:用户id
        :return: token
        """
        s = Serializer(current_app.config["SECRET_KEY"])
        # 接受用户id转换编码
        token = s.dumps({"id": user_id, "user_type": user_type})
        return token




        # import time
        #
        # # 使用 Serializer 进行编码，不直接设置过期时间
        # s = Serializer(current_app.config["SECRET_KEY"])
        # # 接受用户id转换编码
        # data = {"id": user_id, "user_type": user_type}
        # token = s.dumps(data)  # 移除 .decode("ascii")
        #
        # # 添加过期时间戳
        # expire_time = int(time.time()) + current_app.config["TOKEN_EXPIRES"]
        # signer = TimestampSigner(current_app.config["SECRET_KEY"])
        # signed_token = signer.sign(f"{token}:{expire_time}".encode('utf-8')).decode('ascii')
        # print(signed_token)
        # return signed_token

    # token信息持久化(保存到MySQL数据库中或者Redis中)；
    @classmethod
    def save_token(cls, **kwargs):

        user_token = AdministratorToken(
            user_id=kwargs.get('user_id'),
            user_type=kwargs.get('user_type'),
            token=kwargs.get('token'),
            expire_time=kwargs.get('expire_time'),
        )
        try:
            db.session.add(user_token)
            db.session.commit()

        except Exception as e:
            loggings.exception(1, e)
            db.session.rollback()
            return None

        return user_token

    # 通过user_id获取token
    @classmethod
    def get_token(cls, **kwargs):
        user_token = db.session.query(cls).filter(cls.user_id == kwargs.get('user_id'),
                                                  cls.is_delete == 0, cls.is_valid == 1)
        if not user_token.first():
            return None
        else:
            return user_token

    # 通过token获取用户信息
    @classmethod
    def get_user_by_token(cls, token):
        """
        校验token
        :param token:token值
        :return: 用户信息 or None
        """
        # 参数为私有密钥，与生成token的密钥一致
        s = Serializer(current_app.config["SECRET_KEY"])
        try:
            # 转换为字典
            data = s.loads(token)
        except Exception as e:
            loggings.exception(1, e)
            return {'code': RET.DBERR, 'message': '用户未登录或登录已过期', 'error': '用户未登录或登录已过期'}

        # 拿到转换的后的数据，根据模型类去数据库查询用户信息
        if data['user_type'] == 0:  # 学生/普通用户
            filter_list = [User.is_delete == 0, User.user_id == data['id']]

            try:
                student_model = db.session.query(User).filter(*filter_list).first()

                if not student_model:
                    return {'code': RET.NODATA, 'message': '无用户信息(或已删除)', 'error': '无用户信息(或已删除)'}
                else:
                    student = commons.query_to_dict(student_model)
                    # 将StudentID键名替换为UserID，保存在g对象中
                    student['user_id'] = student.pop('user_id')
                    student['user_type'] = 0
                    return {'code': RET.OK, 'message': 'OK', 'data': student}
            except Exception as e:
                loggings.exception(1, e)
                return {'code': RET.DBERR, 'message': '数据库异常，获取学生用户信息失败',
                        'error': '数据库异常，获取学生用户信息失败'}
            finally:
                db.session.close()
        elif data['user_type'] == 1:  # 管理员
            filter_list = [Administrator.is_delete == 0, Administrator.administrator_id == data['id']]

            try:
                sys_user_model = db.session.query(Administrator).filter(*filter_list).first()

                if not sys_user_model:
                    return {'code': RET.NODATA, 'message': '无管理员用户信息(或已删除)', 'error': '无管理员用户信息(或已删除)'}
                else:
                    sys_user = commons.query_to_dict(sys_user_model)
                    # 将StudentID键名替换为UserID，保存在g对象中
                    sys_user['user_id'] = sys_user.pop('administrator_id')
                    sys_user['user_type'] = 1
                    return {'code': RET.OK, 'message': 'OK', 'data': sys_user}
            except Exception as e:
                loggings.exception(1, e)
                return {'code': RET.DBERR, 'message': '数据库异常，获取管理员用户信息失败', 'error': '数据库异常，获取管理员用户信息失败'}
            finally:
                db.session.close()

    @classmethod
    def logout(cls, **kwargs):

        user_token_model = cls.get_token(**kwargs)
        if not user_token_model:
            return {'code': RET.SESSIONERR, 'message': '用户已退出', 'error': '用户已退出'}

        try:
            user_token_model.update({
                'is_valid': 0
            }, synchronize_session=False)
            db.session.commit()
        except Exception as e:
            db.session.rollback()
            loggings.exception(1, e)
            return {'code': RET.DBERR, 'message': '数据库异常，用户退出失败', 'error': '数据库异常，用户退出失败'}
        finally:
            db.session.close()

        return {'code': RET.OK, 'message': 'OK'}